﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using System.Collections.Generic;
using DiscoveryLogic.UI.Layouts.ContentScreens;
using DiscoveryLogic.UI.Layouts.Controls;
using DiscoveryLogic.UI.Layouts.DataAccesses;
using DiscoveryLogic.UI.Layouts.Models;
using DiscoveryLogic.DataServices.DataSources;
using System.Globalization;

namespace DiscoveryLogic.UI.Layouts.DataAcccesses
{
    public class TradeHistoryManager : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        #region Private Variables

            List<Trade> listOfLocalTrades = null;
            List<Trade> listOfWSTrades = null;

            List<TradeHistoryNewsItem> listOfLocalNews = null;
            List<TradeHistoryNewsItem> listOfWSNews = null;

        private ObservableCollection<TradeHistoryNewsItem> _filteredNews = null;
        private int _selectedNewsIndex = -1;

        private bool _worldwideNews = true;
        private bool _industryNews = true;
        private bool _companyNews = true;
        private bool _trivialNews = true;

            private readonly bool enableWebService = false;

        #endregion

        #region Constructors

            public TradeHistoryManager()
            {               
            }

        #endregion


        #region Public Methods

        /// <summary>
        /// WorldwideNews depicts whether FilteredNews contains worldwide news
        /// </summary>
        public bool WorldwideNews
        {
            get { return _worldwideNews; }
            set
            {
                _worldwideNews = value;
                UpdateFilteredNews();
                NotifyPropertyChanged("WorldwideNews");
            }
        }

        /// <summary>
        /// IndustryNews depicts whether FilteredNews contains industry news
        /// </summary>
        public bool IndustryNews
        {
            get { return _industryNews; }
            set
            {
                _industryNews = value;
                UpdateFilteredNews();
                NotifyPropertyChanged("IndustryNews");
            }
        }

        /// <summary>
        /// CompanyNews depicts whether FilteredNews contains company news
        /// </summary>
        public bool CompanyNews
        {
            get { return _companyNews; }
            set
            {
                _companyNews = value;
                UpdateFilteredNews();
                NotifyPropertyChanged("CompanyNews");
            }
        }

        /// <summary>
        /// TrivialNEws depicts whether FilteredNews contains trivial news
        /// </summary>
        public bool TrivialNews
        {
            get { return _trivialNews; }
            set
            {
                _trivialNews = value;
                UpdateFilteredNews();
                NotifyPropertyChanged("TrivialNews");
            }
        }

        /// <summary>
        /// SelectedNewsIndex is the 0-based index into FilteredNews for the selected / highlighted news item
        /// </summary>
        public int SelectedNewsIndex
        {
            get { return _selectedNewsIndex; }
            set
            {
                _selectedNewsIndex = value;
                NotifyPropertyChanged("SelectedNewsIndex");
            }
        }

        /// <summary>
        /// FilteredNews is an observable collection of the news items, filtered using the xxxNews properties, e.g. WorldwideNews
        /// </summary>
        public ObservableCollection<TradeHistoryNewsItem> FilteredNews
        {
            get
            {
                if (_filteredNews == null)
                    UpdateFilteredNews();
                return _filteredNews;
            }
        }

            public List<TradeHistoryNewsItem> GetNews()
            {
                if (enableWebService)
                {
                    return this.WSNews;
                }
                else
                {
                    return this.LocalNews;
                }
            }

            private List<TradeHistoryNewsItem> LocalNews
            {
                get
                {
                    if (listOfLocalNews == null)
                    {
                        List<NewsItem> listOfNewsItems = new List<NewsItem>(LocalDataFiles.LoadData<NewsItem[]>("DiscoveryLogic.UI.Layouts.LocalDataFiles.TradeHistoryNews.xml"));

                        List<TradeHistoryNewsItem> listOfNews = new List<TradeHistoryNewsItem>();

                        for (int i = 0; i < listOfNewsItems.Count; i++)
                        {
                            listOfNews.Add(new TradeHistoryNewsItem(listOfNewsItems[i].id, listOfNewsItems[i].newsType, listOfNewsItems[i].headline, listOfNewsItems[i].body, listOfNewsItems[i].newsDate));

                        }

                        //make all the dates between now and 3 months in the past!!!!
                        DateTime start = DateTime.Today.Add(TimeSpan.FromDays(-120));
                        DateTime end = DateTime.Today.Add(TimeSpan.FromDays(-1));
                        IEnumerable<DateTime> originalDates = listOfNews.Select(l => l.NewsDate);
                        listOfNews.ForEach(date =>
                            date.NewsDate = Utils.MoveDateWithinRange(originalDates, date.NewsDate, start, end));


                        listOfLocalNews = listOfNews;
                    }

                    return listOfLocalNews;
                }
            }

            private List<TradeHistoryNewsItem> WSNews
            {
                get
                {
                    if (listOfWSNews == null)
                    {
                        // Retrieve list of TradeHistoryNewsItem obj from WS
                    }

                    return listOfWSNews;
                }
            }

        /// <summary>
        /// UpdateFilteredNews resets _filteredNews to contain only the current news items based on the filtering
        /// properties, WorldwideNews, etc.
        /// </summary>
        private void UpdateFilteredNews()
        {
            if (_filteredNews == null)
                _filteredNews = new ObservableCollection<TradeHistoryNewsItem>();
            _filteredNews.Clear();

            List<TradeHistoryNewsItem> news = GetNews();

            // Use LINQ to filter the list of news based on the items that are currently selected
            // Strictly speaking this is not going to be that efficient, since we convert the IEnumerable
            // from LINQ into a List which we then convert into an ObservableCollection. In a real world
            // sample we might want to filter from a larger list of news on the company type as well,
            // in which case might end up being more inefficient.
            var result = from n in news
                        where ((_worldwideNews && n.NewsType==NewsTypes.Worldwide)
                        || (_industryNews && n.NewsType==NewsTypes.Industry)
                        || (_companyNews && n.NewsType == NewsTypes.Company)
                        || (_trivialNews && n.NewsType == NewsTypes.Trivial))
                        select n;

            result.ToList().ForEach(n => _filteredNews.Add(n));
        }

            // Calls webservice and returns list of Account objects if WS is enabled.
            public List<Trade> GetTrades()
            {
                //JAIMER  hack to get around async WS problem .. 
                // Chris: Commented out WS
                //if (enableWebService || this.WSAccounts == null )
                if (enableWebService)
                {
                    return this.WSTrades;
                }
                else
                {
                    return this.LocalTrades;
                }
            }

            private List<Trade> LocalTrades
            {
                get
                {
                    if (listOfLocalTrades == null)
                    {
                        listOfLocalTrades = new List<Trade>(LocalDataFiles.LoadData<Trade[]>("DiscoveryLogic.UI.Layouts.LocalDataFiles.TradeHistoryTrades.xml"));

                        //Unfortunaetly the date in the xml file is in an american style date.
                        CultureInfo culture = new CultureInfo("en-US");

                        //make all the dates between now and 3 months in the past!!!!\
                        DateTime start = DateTime.Today.Add(TimeSpan.FromDays(-120));
                        DateTime end = DateTime.Today.Add(TimeSpan.FromDays(-1));
                        IEnumerable<DateTime> originalDates = listOfLocalTrades.Select(l => ToDate(l.Date, culture));
                        listOfLocalTrades.ForEach(date =>
                            date.Date = FromDate(Utils.MoveDateWithinRange(originalDates, ToDate(date.Date, culture), start, end), culture));

                    }

                    return listOfLocalTrades;
                }
            }

            private List<Trade> WSTrades
            {
                get
                {
                    if (listOfWSTrades == null)
                    {
                        // Retrieve list of trade obj from WS
                    }

                    return listOfWSTrades;
                }
            }

        private DateTime ToDate(string dateStr, CultureInfo culture)
        {
            return Convert.ToDateTime(dateStr, culture);
        }
        private string FromDate(DateTime date, CultureInfo culture)
        {
            return date.ToString("d", culture);
        }


        /// <summary>
        /// NotifyPropertyChanged is used as a wrapper for firing the PropertyChanged event handler when our properties are
        /// updated. The TradeHistory.xaml and StockChart.xaml files use this for data binding of the news list and stock
        /// chart news markers.
        /// </summary>
        /// <param name="propertyName"></param>
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged!=null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

    }
}
